package cn.iocoder.boot.springai001.controller;

import cn.iocoder.boot.springai001.controller.dto.CancelRequest;
import cn.iocoder.boot.springai001.controller.dto.ChatRequest;
import cn.iocoder.boot.springai001.service.CancellationService;
import cn.iocoder.boot.springai001.service.ChatService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.model.Generation;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

/**
 * AI对话控制器
 * <p>
 * 统一的对话接口，支持多种对话模式动态选择
 * <p>
 * API路径：POST /api/v1/chat - 统一的AI对话接口
 */
@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/api/v1/chat")
@Tag(name = "AI对话接口", description = "提供统一的智能对话功能，支持多种对话模式")
public class ChatController {

    @Resource
    private ChatService chatService;

    @Resource
    private CancellationService cancellationService;

    /**
     * 统一的对话接口
     * <p>
     * 根据请求参数中的 chatMode 动态选择对话模式：
     * - BASIC: 基础对话模式（默认）
     * - TASK_PLANNING: 任务规划模式
     * - STREAMING_TOOLS_MANUAL: 流式工具调用模式（手动模式）
     * <p>
     * 所有功能都通过 chatMode 参数动态选择
     */
    @Operation(
            summary = "统一对话接口",
            description = "统一的AI对话接口，支持多种对话模式动态选择。" +
                    "通过 chatMode 参数选择：BASIC（基础对话）、TASK_PLANNING（任务规划）、STREAMING_TOOLS_MANUAL（流式工具调用）。"
    )
    @PostMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<Generation> streamChat(@RequestBody ChatRequest request) {

        // 参数校验
        if (request.getQuery() == null || request.getQuery().trim().isEmpty()) {
            log.error("问题内容为空");
            return Flux.error(new IllegalArgumentException("问题内容不能为空"));
        }
        // 调用服务进行对话（内部会根据 chatMode 自动选择对应的处理逻辑）
        return chatService.chat(request).mapNotNull(ChatResponse::getResult);
    }

    @Operation(
            summary = "取消正在进行的对话",
            description = "用于前端在流式对话过程中显式取消任务。优先使用 requestId，若缺失则回退 sessionId。"
    )
    @PostMapping(value = "/cancel")
    public ResponseEntity<Void> cancelChat(@RequestBody CancelRequest request) {
        String cancelKey = StringUtils.hasText(request.getRequestId())
                ? request.getRequestId()
                : request.getSessionId();

        if (!StringUtils.hasText(cancelKey)) {
            log.warn("取消请求缺少 requestId/sessionId");
            return ResponseEntity.badRequest().build();
        }

        boolean cancelled = cancellationService.cancel(cancelKey);
        return cancelled ? ResponseEntity.accepted().build() : ResponseEntity.notFound().build();
    }

}

